#include<map>
#include<string>
#include<memory>
#include <sys/types.h>
#include <dirent.h>
#include<dlfcn.h>
#include<omp.h>
#include"c3pom/Object.h"
#include"c3pom/Kernel.h"
#include"c3pom/Portal.h"
#include"c3pom/Plugin.h"
#include"c3pom/dynclass.h"
#include"c3pom/macro.h"
#include<iostream>

using std::string;
using std::map;
using std::cout;
using std::endl;

Kernel::Kernel(int argc,char** argv)
{
	log("初始化");
	attribute["running"]=true;
	attribute["plugin_dir"]="/opt/c3pom/plugins";
	attribute["portal_buf_dir"]="/opt/c3pom/portal_bufs";
	attribute["argc"]=argc;
	attribute["argv"]=argv;
	omp_init_lock(&portalmap_lock);
	log("初始化Kernel完毕");
}

//kernel运行
void Kernel::run()
{
	//此处将会更换成openmp采用并行方式执行以下代码，相互每个功能初步定位为论循方式（仅主体部分），其他部分不变
	try{
		while(attribute["running"].castto<bool>())
		{
			log("开始更新插件目录");
			updatepluginlist();//更新插件目录
			log("更新插件目录完毕");
			updateportalbuflist();
			log("更新portalbuf完毕");
			loadallplugin();//加载所有的插件
			log("加载插件完毕");
			runallplugin();//启动所有的插件
			log("启动插件完毕");
			shell();//启动shell
		}
	}
	catch(...)
	{ 
		//log("ERRO:something wrong");//c3pom运行时发生了某些错误
		return;
	}
}

//portal操作部分
Portal Kernel::regportal(string portal_name,map<string,Object> cond)
{
	cout<<"portal:"<<portal_name<<"正在被注册"<<endl;
	omp_set_lock(&portalmap_lock);//锁定	
	cond["portal_instance"]=new Portal(cond["Portal_Buf_class"].castto<char*>());
	portals[portal_name]=cond;//这里采用归并更好,后期进行
	omp_unset_lock(&portalmap_lock);//解锁
	cout<<"portal:"<<portal_name<<"注册成功"<<endl;
	return *(portals[portal_name]["portal_instance"].castto<Portal*>());
}

Portal Kernel::findportal(map<string,Object> cond)
{
	return *(portals[cond["name"].castto<string>()]["portal_instance"].castto<Portal*>());//根据转换后的获取的名称查找portal
}

Portal& Kernel::findportal(string name)
{
	omp_set_lock(&portalmap_lock);
	Object o=portals[name]["portal_instance"];
	omp_unset_lock(&portalmap_lock);
	if(o.isnull())
		return *(new Portal());//返回一个空的portal
	return *(o.castto<Portal*>());//返回找到了到portal
}

void Kernel::updateportalinfo(Portal newp)
{
}

void Kernel::delportal()
{
}

void Kernel::updateportalbuflist()
{
	DIR *dirptr=NULL;
	struct dirent *entry;
	if(NULL==(dirptr=opendir(attribute["portal_buf_dir"].castto<char*>())))
	{
		return;
	} 
	while(NULL!=(entry=readdir(dirptr)))
	{ 
		if(0==strcmp(entry->d_name,".")||0==strcmp(entry->d_name,".."))
			continue;
		log("当前读取的portal_buf是");
		log(entry->d_name);
		map<string,Object> m;
		portal_bufs[string(attribute["portal_buf_dir"].castto<char*>())+"/"+entry->d_name]=m;
		loadportalbuf(string(attribute["portal_buf_dir"].castto<char*>())+"/"+entry->d_name);

	}
	closedir(dirptr);
}

void Kernel::loadportalbuf(string name)
{
	try{
		log("当前加载的portal_buf是");
		log(name);
		void* handle=dlopen(name.c_str(),RTLD_LAZY|RTLD_NODELETE);
		if(handle==NULL)
		{
			log(dlerror());
		} 
		else
		{ 
			log(name);
			log("文件读取成功");
		}
		string pname(name,name.find("lib")+3,name.find(".so")-name.find("lib")-3);
		void (*reg_class)();
		log("尝试注册portal_buf:");
		log(name);
		reg_class=(void (*)())dlsym(handle,"C3POM_reg_class");
		if(reg_class==NULL)
		{
			log(dlerror());
		}
		else
		{ 
			log("获取注册句柄成功");
		}
		(*reg_class)();
		log("portal_buf:");
		log(name);
		log("注册成功");
		portal_bufs[name]["dlopen_handle"]=handle;
	} 
	catch(...)
	{
		return;
	} 
}

//envar操作部分
void Kernel::setenvar(string name,Object value)
{
	envar[name]=value;
}

Object Kernel::getenvar(string name)
{
	return envar[name];
}

void Kernel::delenvar(string name)
{
	envar.erase(name);
}

//attribute操作部分
Object Kernel::getattribute(string name)
{
	return attribute[name];
}

//plugin操作部分
void Kernel::updatepluginlist()
{
	DIR *dirptr = NULL;
	struct dirent *entry;
	if((dirptr = opendir(attribute["plugin_dir"].castto<char*>())) == NULL)
	{
		//log("ERRO:plugin list dir can not be opened!");
		return;
	}
	while(NULL!=(entry=readdir(dirptr)))
	{
		if(0==strcmp(entry->d_name,".")||0==strcmp(entry->d_name,".."))
			continue;
		//对于ln还有不符合条件的插件文件的过滤工作将放到后期进行,目前仅保证能读取到所有文件,并假定他们都是"正确的"插件文件
		//if(plugins[entry->d_name])//将所有找到的插件文件添加到plugin列表中,对于首次被添加进来的插件,会进行map的初始化工作
		//{
		map<string,Object> m;
		plugins[string(attribute["plugin_dir"].castto<char*>())+"/"+entry->d_name]=m;
		//}
	}
	closedir(dirptr);
}

//需完善!!!!!
void Kernel::loadplugin(string name)//参数为完整路径
{
	//Plugin文件的命名形式为lib*****.so,*****为入口类的类名
	try{
		log("当前加载的插件是");
		log(name);
		void* handle=dlopen(name.c_str(),RTLD_LAZY|RTLD_NODELETE);
		if(handle==NULL)
		{
			log(dlerror());
		}
		else
		{
			log(name);
			log("文件句柄获取成功");
		}
		string pname(name,name.find("lib")+3,name.find(".so")-name.find("lib")-3);//这里会将name进行适当的转换以提取出真实的类名
		void (*reg_class)();
		log("尝试注册插件");
		log(name);
		reg_class=(void (*)())dlsym(handle,"C3POM_reg_class");//找到插件文件中注册入口类的函数
		if(reg_class==NULL)
		{
			log(dlerror());
		}
		else
		{
			log("插件");
			log(name);
			log("注册函数获取成功");
		}
		log("尝试创建插件实例");
		(*reg_class)();//执行类注册
		log("插件注册函数执行成功");
		Plugin*	p=(Plugin*)DYN_CREATE(pname.c_str());//根据类名创建对象实例
		if(NULL==p)
		{
			log("DYN_CREATE失败");
		}
		else
		{
			log("注册插件");
			log(name);
			log("成功");
		}
		p->setattr("kernel_instance",this);//将p实例中注册上kernel的指针
		plugins[name]["plugin_instance"]=p;//将插件的实例存放到对应的map属性中;
		plugins[name]["dlopen_handle"]=handle;//将打开的文件句柄保存
		//	plugins[name]["load_time"]=gettimeofday();//首次加载时间
		//	plugins[name]["md5"];//文件的md5值用于校验文件变动(或许用的着)
		//	plugins[name]["plugin_statu"]="init finished";//插件状态:初始化完毕
		log("加载插件成功");
	}
	catch(...)
	{
		//log("ERRO:something happened when reg_new_plugin);
		return;
	}
}

void Kernel::loadallplugin()
{
	map<string,map<string,Object> >::const_iterator map_it=plugins.begin();

	for(;map_it!=plugins.end();map_it++)
	{
		loadplugin(map_it->first);//加载所有的插件
	}
}

void Kernel::runallplugin()
{
	//omp_set_num_threads(6);
#pragma omp parallel
	for(map<string,map<string,Object> >::const_iterator map_it=plugins.begin();map_it!=plugins.end();map_it++)
	{
#pragma omp single nowait
		runplugin(map_it->first);
	}
}


void Kernel::runplugin(string name)
{
	try{
		log("启动插件");
		log(name);
		printf("total threads=%d\n",omp_get_num_threads());
		printf("current thread_id=%d\n",omp_get_thread_num());
		if(0<omp_get_thread_num())//子线程执行而主线程不需要等待
		{
			log("开始启动");
			plugins[name]["plugin_instance"].castto<Plugin*>()->run();
		}
		printf("total threads=%d----\n",omp_get_num_threads());
	}

	catch(...)
	{
		//log("ERRO:plugin "+name+" start failed or something wrong while running");
	}
}

void Kernel::hangplugin()
{
}

void Kernel::wakeplugin()
{
}

void Kernel::stopplugin()
{
}


void Kernel::shell(){
	printallportals();//输出全部已注册的portal
}

void Kernel::printallportals(){
	printf("name\t|\tdesc\n");
	map<string,Object>::iterator it;
	//for(it=portals.begin();it!=portals.end();++it)
	{
		//printf("%s",it->first().c_str());//portal的名字
		//printf("%s",portals[it->first()]["desc"].c_str());//portal的描述
		//printf("\n");
		//flush();
	}
}
